package com.project.demo.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class PDPDataIntegrityVerification {

    private static final int BLOCK_SIZE = 100; // 块大小，单位：字节
    private static final String HASH_ALGORITHM = "SHA-256";


    // 计算文件各块的哈希值
    public static List<String> calculateBlockHashes(File file) throws IOException, NoSuchAlgorithmException {
        List<String> blockHashes = new ArrayList<>();
        try (FileInputStream fis = new FileInputStream(file)) {
            byte[] buffer = new byte[BLOCK_SIZE];
            int bytesRead;
            MessageDigest digest = MessageDigest.getInstance(HASH_ALGORITHM);
            while ((bytesRead = fis.read(buffer)) != -1) {
                digest.update(buffer, 0, bytesRead);
                byte[] hashBytes = digest.digest();
                StringBuilder hexString = new StringBuilder();
                for (byte b : hashBytes) {
                    String hex = Integer.toHexString(0xff & b);
                    if (hex.length() == 1) {
                        hexString.append('0');
                    }
                    hexString.append(hex);
                }
                blockHashes.add(hexString.toString());
                digest.reset();
            }
        }
        return blockHashes;
    }

    // 生成挑战
    public static List<Integer> generateChallenge(int blockCount, int challengeSize) {
        if (blockCount < challengeSize) {
            throw new IllegalArgumentException("块数量小于挑战所需的块数量，无法生成有效的挑战。");
        }
        List<Integer> challenge = new ArrayList<>();
        Random random = new Random();
        while (challenge.size() < challengeSize) {
            int index = random.nextInt(blockCount);
            if (!challenge.contains(index)) {
                challenge.add(index);
            }
        }
        return challenge;
    }

    // 生成响应
    public static List<String> generateResponse(List<String> blockHashes, List<Integer> challenge) {
        List<String> response = new ArrayList<>();
        for (int index : challenge) {
            response.add(blockHashes.get(index));
        }
        return response;
    }

    // 验证响应
    public static boolean verifyResponse(List<String> originalBlockHashes, List<String> currentBlockHashes, List<Integer> challenge, List<String> response) {
        for (int i = 0; i < challenge.size(); i++) {
            int index = challenge.get(i);
            String expectedHash = originalBlockHashes.get(index);
            String actualHash = currentBlockHashes.get(index);
            String responseHash = response.get(i);

            System.out.println("挑战索引: " + index);
            System.out.println("原始哈希值: " + expectedHash);
            System.out.println("当前哈希值: " + actualHash);
            System.out.println("响应哈希值: " + responseHash);

            if (!expectedHash.equals(actualHash) || !expectedHash.equals(responseHash)) {
                return false;
            }
        }
        return true;
    }

    public static void main(String[] args) {
        try {
            File file = new File("E:\\test.txt"); // 替换为实际文件路径

            // 计算原始文件的块哈希值
            List<String> originalBlockHashes = calculateBlockHashes(file);
            int blockCount = originalBlockHashes.size();
            int challengeSize = 5;

            // 生成挑战
            List<Integer> challenge = generateChallenge(blockCount, challengeSize);
            System.out.println("挑战：" + challenge);

            // 假设修改文件后重新计算块哈希值
            List<String> currentBlockHashes = calculateBlockHashes(file);

            // 生成响应
            List<String> response = generateResponse(currentBlockHashes, challenge);
            System.out.println("响应：" + response);

            // 验证响应
            boolean isValid = verifyResponse(originalBlockHashes, currentBlockHashes, challenge, response);
            if (isValid) {
                System.out.println("验证成功：数据完整且未被篡改。");
            } else {

                System.out.println("验证失败：数据可能被篡改或损坏。");
            }
        } catch (IOException | NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
    }
}